home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $VER: device-handler.c 1.6 (03 Jun 1995)
- **
- ** device-handler - raw device access
- **
- ** (C) Copyright 1995 Marius Gröger
- ** All Rights Reserved.
- */
-
- /*F*/ /* history */
- /* $HISTORY:
- **
- ** 03 Jun 1995 : 001.006 : + locyl was broken
- ** + dot conversion starts after first slash
- ** + source code ANSIfied
- ** + added some macros for compiler abstraction
- ** + didn't remove task correctly
- ** 24 Apr 1995 : 001.005 : at the end of a media Write()/Read() returned wrong res1,
- ** so multi-volume tar archives shouldn't be a problem any
- ** longer
- ** 22 Feb 1995 : 001.004 : some bug-fixing
- ** 18 Feb 1995 : 001.003 : made Write() working...
- ** 20 Dec 1994 : 001.002 : + one task/multiple FileHandles
- ** + source-code rework
- ** + better stream name scanning by ReadArgs()
- ** + new option MAXLENGTH
- ** + new options LOCYL, HICYL
- ** + highly improved read/write operation
- ** 18 Dec 1994 : 001.001 : changed stream name convention
- ** 08 Dec 1994 : 001.000 : took over from Matthias Scheler
- */
- /*E*/
-
- /*F*/ /* includes */
-
- /* system protoypes and pragmas */
- /* ensure to use the symbol SysBase and not the hardcoded AbsExecBase */
- #define __USE_SYSBASE
- #include <clib/exec_protos.h>
- #include <pragmas/exec_pragmas.h>
- #include <clib/dos_protos.h>
- #include <pragmas/dos_pragmas.h>
- #include <clib/utility_protos.h>
- #include <pragmas/utility_pragmas.h>
-
- /* system header files */
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/execbase.h>
- #include <devices/trackdisk.h>
- #include <dos/dosextens.h>
- #include <dos/filehandler.h>
- #include <dos/dos.h>
-
- /* compiler header files */
- #include <string.h>
-
- /* fix include files (anyawy I'm not yet using them:
- ** what about sending me a diff-file ?)
- */
- #ifndef ACTION_GET_DISK_FSSM
- #define ACTION_GET_DISK_FSSM 4201
- #endif
- #ifndef ACTION_FREE_DISK_FSSM
- #define ACTION_FREE_DISK_FSSM 4202
- #endif
-
- #include "device-handler_rev.h"
-
- /*E*/
-
- /*F*/ /* debug */
- extern void KPrintF(char *, ...);
- /*#define d(x) do { KPrintF("%s:%ld: ", __FUNC__, __LINE__); KPrintF x; } while(0)*/
- #define d(x)
- /*E*/
- /*F*/ /* compiler abstraction */
-
- #ifdef __SASC
- # define ASM __asm
- # define REG(x) register __ ## x
- # define INLINE __inline
- # define REGARGS __regargs
- # define SAVEDS __saveds
- # define FAR __far
- # define MIN __builtin_min
- # define MAX __builtin_max
- #else
- # error Please define the above macros for your compiler
- #endif
-
- /*E*/
-
- /*F*/ /* global static storage */
-
- typedef struct GlobalData
- {
- struct Library *gd_SysBase;
- struct Library *gd_DOSBase;
- struct Library *gd_UtilityBase;
- struct MsgPort *gd_Port;
- struct DosList *gd_DosList;
- struct Process *gd_We;
- } *GD;
-
- #ifdef __SASC
- /* redirect all shared library bases to our device base */
- # define SysBase gd->gd_SysBase
- # define DOSBase gd->gd_DOSBase
- # define UtilityBase gd->gd_UtilityBase
- /* This macro declares a local variable which temporary gets
- SysBase directly from AbsExecBase. */
- # define LOCALSYSBASE struct { VOID *gd_SysBase; } *gd = (VOID*)0x4
- #else
- # error Please define library bases for your compiler
- #endif
- /*E*/
- /*F*/ /* handler declarations */
-
- #define STREAMNAME_TEMPLATE "DOSNAME/A,MAXLENGTH,LOCYL/K,HICYL/K"
-
- struct StreamOpts
- {
- UBYTE *so_DOSName;
- UBYTE *so_MaxLength;
- UBYTE *so_LoCyl;
- UBYTE *so_HiCyl;
- };
-
- #define BCPL_MAXNAME 256
- struct PrivateStreamData
- {
- struct IOStdReq *psd_IO; /* Exec I/O Block */
- UBYTE psd_DOSName[BCPL_MAXNAME]; /* Name of AmigaDOS handler */
- UBYTE psd_Device[32]; /* OpenDevice()-name */
- ULONG psd_Unit; /* OpenDevice()-unit */
- ULONG psd_Flags; /* OpenDevice()-flags */
- ULONG psd_BufMemType; /* memory type needed */
- LONG psd_LoCyl, psd_HiCyl; /* cylinder boundaries */
- LONG psd_SectorSize; /* length of a sector */
- LONG psd_Offset; /* starting sector */
- LONG psd_MaxLength; /* max-length of "file" */
- LONG psd_Pos; /* current pos. in "file" */
- LONG psd_Len; /* actual length of "file" */
- UBYTE *psd_Buffer; /* r/w buffer */
- LONG psd_Left; /* bytes left in r/w buffer */
- UBYTE *psd_Ptr; /* current pos in buffer */
- BOOL psd_Write; /* file is in write mode */
- struct StreamOpts psd_Param; /* ReadArgs() argument */
- };
-
-
- /*E*/
-
- /*F*/ /* prototypes */
- STATIC struct DosPacket *WaitDosPacket(GD gd, struct MsgPort *port);
- STATIC VOID ReplyDosPacket(GD gd, struct MsgPort *port, struct DosPacket *Packet,LONG Res1,LONG Res2);
- STATIC BOOL GetXDULONG(GD gd, UBYTE *s, LONG *number);
- STATIC VOID Stream2RDArgs(UBYTE *buffer);
- STATIC BOOL StreamSpecs(GD gd, struct PrivateStreamData *psd, BPTR streamname, LONG *res);
- STATIC BOOL FindDevice(GD gd, struct PrivateStreamData *psd);
- STATIC VOID OpenDH(GD gd, struct DosPacket *Pkt,ULONG *OpenCnt);
- STATIC VOID CloseDH(GD gd, struct PrivateStreamData *psd,ULONG *OpenCnt);
- STATIC LONG REGARGS RawRead(GD gd, struct PrivateStreamData *psd, UBYTE *Buffer, LONG Bytes, LONG *res2);
- STATIC LONG REGARGS RawWrite(GD gd, struct PrivateStreamData *psd,UBYTE *Buffer,LONG Bytes, LONG *res2);
- STATIC GD creategd(VOID);
- STATIC BOOL openres(GD gd);
- STATIC VOID closeres(GD gd);
- GLOBAL LONG main(VOID);
- /*E*/
-
- /*F*/ GLOBAL LONG SAVEDS main(VOID)
- /*
- ** don't remove GLOBAL, if you don't want to the complete
- ** source to get optimized out of existence :-)
- */
- {
- GD gd;
- struct DosPacket *Pkt;
- BOOL Done;
- ULONG OpenCnt;
- LONG rc = RETURN_OK;
-
- d(("this is the DEV handler, compiled on "__DATE__"\n"));
-
- if (gd = creategd())
- {
- if ((gd->gd_We = (struct Process *)FindTask(NULL))->pr_CLI) return RETURN_FAIL;
-
- d(("waiting for startup-packet...\n"));
- Pkt = WaitDosPacket(gd, &gd->gd_We->pr_MsgPort);
-
- if (openres(gd))
- {
- gd->gd_DosList = (struct DosList *)BADDR(Pkt->dp_Arg3);
- gd->gd_DosList->dol_Task = gd->gd_Port;
-
- d(("replying startup-packet...\n"));
- ReplyDosPacket(gd, gd->gd_Port, Pkt, DOSTRUE, Pkt->dp_Res2);
-
- Done=FALSE;
- OpenCnt=0L;
-
- d(("entering mainloop\n"));
-
- while (!Done)
- {
- Pkt=WaitDosPacket(gd, gd->gd_Port);
-
- d(("got packet %ld\n",Pkt->dp_Type));
-
- Pkt->dp_Res1 = DOSFALSE;
- Pkt->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
-
- switch (Pkt->dp_Type)
- {
- case ACTION_FINDINPUT:
- case ACTION_FINDOUTPUT:
- OpenDH (gd, Pkt, &OpenCnt);
- ReplyDosPacket(gd, gd->gd_Port,Pkt, Pkt->dp_Res1, Pkt->dp_Res2);
- break;
-
- case ACTION_READ:
- {
- struct PrivateStreamData *psd = (struct PrivateStreamData *)Pkt->dp_Arg1;
-
- if (psd && !psd->psd_Write)
- {
- LONG Bytes, error;
-
- Bytes = RawRead(gd, (struct PrivateStreamData *)Pkt->dp_Arg1,
- (UBYTE *)Pkt->dp_Arg2,Pkt->dp_Arg3, &error);
-
- ReplyDosPacket(gd, gd->gd_Port,Pkt, Bytes, error);
- }
- }
- break;
-
- case ACTION_WRITE:
- {
- struct PrivateStreamData *psd = (struct PrivateStreamData *)Pkt->dp_Arg1;
-
- if (psd && psd->psd_Write)
- {
- LONG Bytes, error;
-
- Bytes = RawWrite(gd, (struct PrivateStreamData *)Pkt->dp_Arg1,
- (UBYTE *)Pkt->dp_Arg2, Pkt->dp_Arg3, &error);
-
- ReplyDosPacket(gd, gd->gd_Port,Pkt, Bytes, error);
- }
- }
- break;
-
- case ACTION_IS_FILESYSTEM:
- ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE, 0);
- break;
-
- case ACTION_SEEK:
- case ACTION_SET_FILE_SIZE:
- ReplyDosPacket(gd, gd->gd_Port,Pkt, -1,ERROR_ACTION_NOT_KNOWN);
- break;
-
- case ACTION_END:
- CloseDH (gd, (struct PrivateStreamData *)Pkt->dp_Arg1,&OpenCnt);
- ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSTRUE, 0);
- /* FALLTHROUGH */
- case ACTION_DIE:
- if (OpenCnt==0L)
- {
- d(("opencnt = 0\n"));
-
- if (IsListEmpty(&gd->gd_Port->mp_MsgList))
- {
- gd->gd_DosList->dol_Task = NULL;
-
- if (Pkt->dp_Type == ACTION_DIE)
- ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSTRUE, 0);
-
- Done=TRUE;
- }
- else
- {
- if (Pkt->dp_Type == ACTION_DIE)
- ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_OBJECT_IN_USE);
- }
- }
- else
- {
- if (Pkt->dp_Type == ACTION_DIE)
- ReplyDosPacket(gd, gd->gd_Port,Pkt, DOSFALSE,ERROR_OBJECT_IN_USE);
- }
- break;
-
- default:
- ReplyDosPacket(gd, gd->gd_Port, Pkt, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
- break;
- }
- }
- }
- else
- {
- ReplyDosPacket(gd, &gd->gd_We->pr_MsgPort, Pkt, DOSFALSE, ERROR_NO_FREE_STORE);
- rc = RETURN_FAIL;
- }
- closeres(gd);
-
- d(("returning\n"));
- }
- else rc = RETURN_FAIL;
-
-
- return rc;
- }
- const STATIC UBYTE version[]=VERSTAG;
- /*E*/
-
- /*F*/ STATIC struct DosPacket *WaitDosPacket(GD gd, struct MsgPort *port)
-
- {
- WaitPort(port);
- return (struct DosPacket *)(GetMsg(port)->mn_Node.ln_Name);
- }
- /*E*/
- /*F*/ STATIC VOID ReplyDosPacket(GD gd, struct MsgPort *port, struct DosPacket *Packet,LONG Res1,LONG Res2)
- {
- struct MsgPort *reply = Packet->dp_Port;
-
- Packet->dp_Port = port;
- Packet->dp_Link->mn_Node.ln_Name = (char *)Packet;
- Packet->dp_Res1 = Res1;
- Packet->dp_Res2 = Res2;
-
- PutMsg (reply, Packet->dp_Link);
- }
- /*E*/
-
- /*F*/ STATIC BOOL GetXDULONG(GD gd, UBYTE *s, LONG *number)
- {
-
- #define IsDigit(c) ((c) >= '0' && (c) <= '9'))
- #define IsXDigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'A' && (c) <= 'F'))
-
- BOOL hex, rc = TRUE;
- ULONG num;
- UBYTE c;
- WORD len;
-
- if (len = strlen(s))
- {
- if (!Strnicmp(s, "0x", 2))
- {
- hex = TRUE;
- s += 2;
- }
- else if (!Strnicmp(s, "$", 2))
- {
- hex = TRUE;
- s++;
- }
- else hex = FALSE;
-
- for(num=0;*s;s++)
- {
- c = ToUpper((ULONG)*s);
- if (hex)
- {
- if (c >= '0' && c <= '9') num = num * 16 + c - '0';
- else if (c >= 'A' && c <= 'F') num = num * 16 + c - '0';
- else break;
- }
- else
- {
- if (c >= '0' && c <= '9') num = num * 10 + c - '0';
- else break;
- }
- }
-
- if (*s)
- {
- if (c == 'K') num *= 1024;
- else if (c == 'M') num *= 1024*1024;
- else rc = FALSE;
- }
- }
- else rc = FALSE;
-
- if (rc) *number = num;
-
- return rc;
- }
- /*E*/
- /*F*/ STATIC VOID Stream2RDArgs(UBYTE *buffer)
- {
- UBYTE *p;
- enum { s_start, s_conv, s_esc, s_quote } s, sb;
-
- for (p = buffer, sb = s = s_start; *p; p++)
- switch(s)
- {
- case s_start: /* no convertion 'til 1st slash */
- if (*p == '"')
- {
- s = s_quote;
- break;
- }
- else if (*p != '/')
- break;
- sb = s = s_conv;
- /* FALLTHROUGH */
- case s_conv: /* conversion state */
- if (*p == '.') *p = '=';
- else if (*p == '/') *p = '\040';
- else if (*p == '"') s = s_quote;
- break;
- case s_esc: /* (asterisk-)escape state */
- s = s_quote;
- break;
- case s_quote: /* quotation state */
- if (*p == '*') s = s_esc;
- if (*p == '"') s = sb;
- break;
- }
- }
- /*E*/
- /*F*/ STATIC BOOL StreamSpecs(GD gd, struct PrivateStreamData *psd, BPTR streamname, LONG *res)
- {
- UBYTE *temp, *bstr, *start;
- BOOL rc = FALSE;
- struct RDArgs *inrda, *rda;
-
- memset(&psd->psd_Param, '\0', (int)sizeof(psd->psd_Param));
-
- bstr = (UBYTE *)BADDR(streamname);
-
- if (temp = AllocVec((ULONG)bstr[0]+2, MEMF_ANY))
- {
- if (inrda = AllocDosObject(DOS_RDARGS, NULL))
- {
- strncpy(temp, bstr+1, bstr[0]);
- temp[bstr[0]] = '\n';
- temp[bstr[0]+1] = '\0';
-
- if (start = (UBYTE*)strchr((char*)temp, ':'))
- {
- Stream2RDArgs(++start);
-
- inrda->RDA_Source.CS_Buffer = start;
- inrda->RDA_Source.CS_Length = strlen(start);
- inrda->RDA_Source.CS_CurChr = 0;
-
- psd->psd_MaxLength = 0x7fffffff;
- psd->psd_LoCyl = 0;
- psd->psd_HiCyl = 0x7fffffff;
-
- d(("readargs(%s)\n",start));
- if (rda = ReadArgs((UBYTE*)STREAMNAME_TEMPLATE, (LONG*)&psd->psd_Param, inrda))
- {
- rc = TRUE;
-
- strcpy(psd->psd_DOSName, (char*)psd->psd_Param.so_DOSName);
-
- if (psd->psd_Param.so_MaxLength)
- rc = GetXDULONG(gd,psd->psd_Param.so_MaxLength, &psd->psd_MaxLength);
-
- if (rc && psd->psd_Param.so_LoCyl)
- rc = GetXDULONG(gd,psd->psd_Param.so_LoCyl, &psd->psd_LoCyl);
-
- if (rc && psd->psd_Param.so_HiCyl)
- rc = GetXDULONG(gd,psd->psd_Param.so_HiCyl, &psd->psd_HiCyl);
-
- d(("after ReadArgs(): doshandler %s maxlen %lu locyl %lu hicyl %lu\n",
- psd->psd_DOSName,psd->psd_MaxLength,psd->psd_LoCyl,psd->psd_HiCyl));
-
- FreeArgs(rda);
- }
- else
- {
- d(("ReadArgs() failed\n"));
- *res = ERROR_BAD_STREAM_NAME;
- }
- }
- else
- {
- d(("no proper name\n"));
- *res = ERROR_BAD_STREAM_NAME;
- }
-
- FreeDosObject(DOS_RDARGS, inrda);
- }
- else
- {
- d(("no RDArgs\n"));
- *res = ERROR_NO_FREE_STORE;
- }
-
- FreeVec(temp);
- }
- else
- {
- d(("no more memory\n"));
- *res = ERROR_NO_FREE_STORE;
- }
-
- return rc;
- }
- /*E*/
-
- /*F*/ STATIC BOOL FindDevice(GD gd, struct PrivateStreamData *psd)
- {
- struct DosList *dol;
- struct FileSysStartupMsg *fssm;
- BOOL rc = FALSE;
- UBYTE *name;
- UBYTE n;
- UBYTE pat[40];
-
- d(("entered: %s\n", psd->psd_DOSName));
-
- n = strlen(psd->psd_DOSName);
-
- if (dol = LockDosList(LDF_READ | LDF_DEVICES))
- {
- while(dol = NextDosEntry(dol, LDF_DEVICES))
- {
- name = (UBYTE*)BADDR(dol->dol_Name);
-
- memset(pat,0,40);
- strncpy(pat,name+1,name[0]);
- d(("%s\n",pat));
-
- if ((n == name[0]) && !Strnicmp((char*)(name+1), psd->psd_DOSName, (LONG)n))
- {
- d(("found\n"));
-
- fssm = (struct FileSysStartupMsg*)BADDR(dol->dol_misc.dol_handler.dol_Startup);
-
- if (fssm)
- {
- struct DosEnvec *de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
-
- d(("found fssm\n"));
-
- /* note: fssm->fssm_Device is a NUL-terminated BSTR!! :-) */
- strcpy((char*)psd->psd_Device, (char*)BADDR(fssm->fssm_Device)+1);
-
- psd->psd_Flags = fssm->fssm_Flags;
- psd->psd_Unit = fssm->fssm_Unit;
- psd->psd_BufMemType = de->de_BufMemType;
- psd->psd_SectorSize = 4 * de->de_SizeBlock;
- if (!psd->psd_Param.so_HiCyl) psd->psd_HiCyl = de->de_HighCyl;
- if (!psd->psd_Param.so_LoCyl) psd->psd_LoCyl = de->de_LowCyl;
- psd->psd_LoCyl = (LONG)MIN((int)psd->psd_LoCyl, (int)psd->psd_HiCyl);
- d(("de->de_BlocksPerTrack %ld, psd->psd_LoCyl %ld, psd->psd_HiCyl %ld, de->de_Surfaces %ld, psd->psd_SectorSize %ld\n",
- de->de_BlocksPerTrack, psd->psd_LoCyl, psd->psd_HiCyl, de->de_Surfaces, psd->psd_SectorSize));
- psd->psd_Offset = de->de_BlocksPerTrack * psd->psd_LoCyl * de->de_Surfaces * psd->psd_SectorSize;
-
- psd->psd_Len = de->de_BlocksPerTrack * psd->psd_SectorSize * (psd->psd_HiCyl - psd->psd_LoCyl + 1) * de->de_Surfaces;
- psd->psd_Len = (LONG)MIN((int)psd->psd_MaxLength, (int)psd->psd_Len);
- d(("len %lu\n",psd->psd_Len));
-
- d(("device %s, unit %ld, flags %ld, secsiz %ld, off %ld\n",
- psd->psd_Device,psd->psd_Unit,psd->psd_Flags,psd->psd_SectorSize,psd->psd_Offset));
-
- rc = TRUE;
- }
- else
- d(("no fssm\n"));
-
- break;
- }
- }
-
- UnLockDosList(LDF_READ | LDF_DEVICES);
- }
-
- return(rc);
- }
- /*E*/
-
- /*F*/ STATIC VOID OpenDH(GD gd, struct DosPacket *Pkt,ULONG *OpenCnt)
- {
- struct FileHandle *FH;
- struct PrivateStreamData *psd;
- struct MsgPort *IOPort;
- BOOL ok = FALSE;
-
- Pkt->dp_Res1 = DOSFALSE;
- FH = (struct FileHandle *)BADDR(Pkt->dp_Arg1);
- FH->fh_Port = (struct MsgPort *)FALSE;
- FH->fh_Arg1 = 0L;
-
- d(("allocing psd\n"));
- if (psd = AllocVec(sizeof(*psd),MEMF_PUBLIC|MEMF_CLEAR))
- {
- if (StreamSpecs(gd, psd, (BPTR)Pkt->dp_Arg3, &Pkt->dp_Res2))
- {
- d(("creating msgport\n"));
- if (IOPort=CreateMsgPort())
- {
- if (psd->psd_IO=CreateIORequest(IOPort, sizeof(struct IOStdReq)))
- {
- if (FindDevice(gd, psd))
- {
- if (OpenDevice(psd->psd_Device, psd->psd_Unit, (struct IORequest *)psd->psd_IO, psd->psd_Flags)==0L)
- {
- if (psd->psd_Buffer = AllocVec(psd->psd_SectorSize, psd->psd_BufMemType))
- {
- if (Pkt->dp_Type == ACTION_FINDOUTPUT)
- {
- psd->psd_Write = TRUE;
- }
- else
- {
- psd->psd_Write = FALSE;
- psd->psd_IO->io_Command = CMD_READ;
- }
- psd->psd_Ptr = psd->psd_Buffer;
- psd->psd_Pos = 0;
- psd->psd_Left = 0;
-
- FH->fh_Arg1 = (LONG)psd;
-
- Pkt->dp_Res1 = DOSTRUE;
- Pkt->dp_Res2 = 0L;
-
- (*OpenCnt)++;
- ok = TRUE;
- }
- else Pkt->dp_Res2 = ERROR_NO_FREE_STORE;
-
- if (!ok) CloseDevice ((struct IORequest *)psd->psd_IO);
- }
- else
- {
- d(("could not open device >%s<\n",psd->psd_Device));
- Pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- }
- }
- else
- {
- d(("no device\n"));
- Pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
- }
-
- if (!ok) DeleteIORequest(psd->psd_IO);
- }
- else
- {
- d(("no iorequest\n"));
- Pkt->dp_Res2 = ERROR_NO_FREE_STORE;
- }
-
- if (!ok) DeleteMsgPort (IOPort);
- }
- else
- {
- d(("no msgport\n"));
- Pkt->dp_Res2 = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- d(("no StreamSpecs()\n"));
- }
- if (!ok) FreeVec (psd);
- }
- else
- {
- d(("no psd\n"));
- Pkt->dp_Res2 = ERROR_NO_FREE_STORE;
- }
-
- d(("leaving OpenDH() with Res2 = %ld\n",Pkt->dp_Res2));
- }
- /*E*/
- /*F*/ STATIC VOID CloseDH(GD gd, struct PrivateStreamData *psd,ULONG *OpenCnt)
- {
- d(("CloseDH()\n"));
- if (psd->psd_Write)
- {
- if (psd->psd_Left < psd->psd_SectorSize)
- {
- d(("DoIO(CMD_WRITE)\n"));
-
- memset(psd->psd_Ptr,'\0',(size_t)psd->psd_Left);
- psd->psd_IO->io_Length = psd->psd_SectorSize;
- psd->psd_IO->io_Data = psd->psd_Buffer;
- psd->psd_IO->io_Offset = psd->psd_Pos + psd->psd_Left-psd->psd_SectorSize;
- psd->psd_IO->io_Command = CMD_WRITE;
- DoIO((struct IORequest *)psd->psd_IO);
- }
- psd->psd_IO->io_Command=CMD_UPDATE;
-
- d(("DoIO(CMD_UPDATE)\n"));
- DoIO((struct IORequest *)psd->psd_IO);
- }
-
- d(("FreeVec() buffer\n"));
-
- FreeVec(psd->psd_Buffer);
-
- d(("stopping motor off\n"));
- psd->psd_IO->io_Command = TD_MOTOR;
- psd->psd_IO->io_Length = 0L;
- DoIO((struct IORequest *)psd->psd_IO);
- d(("closing device\n"));
- CloseDevice ((struct IORequest *)psd->psd_IO);
-
- d(("deleting msg port\n"));
- DeleteMsgPort (psd->psd_IO->io_Message.mn_ReplyPort);
-
- d(("deleting stdio\n"));
- DeleteIORequest (psd->psd_IO);
-
- d(("FreeVec() rh\n"));
- FreeVec (psd);
-
- (*OpenCnt)--;
-
- d(("leaving closedh()\n"));
-
- }
- /*E*/
-
- /*F*/ STATIC LONG REGARGS RawRead(GD gd, struct PrivateStreamData *psd, UBYTE *Buffer, LONG Bytes, LONG *res2)
- {
- LONG LatchBytes, RDBytes;
- BOOL error = FALSE;
-
- /* check bouunds */
- if ((psd->psd_Pos + Bytes) > psd->psd_Len) Bytes = psd->psd_Len - psd->psd_Pos;
-
- LatchBytes = Bytes;
-
- d(("read %ld bytes\n",Bytes));
-
- /*
- ** first, read what's left in buffer
- */
- if (psd->psd_Left)
- {
- RDBytes = (LONG)MIN((int)psd->psd_Left, (int)Bytes);
- CopyMem(psd->psd_Ptr, Buffer, RDBytes);
-
- Buffer += RDBytes;
- Bytes -= RDBytes;
-
- psd->psd_Pos += RDBytes; /* incr. position in file */
- psd->psd_Ptr += RDBytes;
- psd->psd_Left -= RDBytes;
- }
-
- /*
- ** second, try to read as much blocks as possible directly to
- ** user buffer, aVOIDing CopyMem()
- */
- if (!error && (Bytes > psd->psd_SectorSize))
- {
- RDBytes = (Bytes / psd->psd_SectorSize) * psd->psd_SectorSize;
-
- psd->psd_IO->io_Data = Buffer;
- psd->psd_IO->io_Length = RDBytes;
- psd->psd_IO->io_Offset = psd->psd_Pos + psd->psd_Offset;
- if (DoIO((struct IORequest *)psd->psd_IO))
- {
- RDBytes = psd->psd_IO->io_Actual;
- error = TRUE;
- *res2 = psd->psd_IO->io_Error;
- }
- Buffer += RDBytes;
- Bytes -= RDBytes;
-
- psd->psd_Pos += RDBytes; /* incr. position in file */
- psd->psd_Left = 0; /* for safety, initialise buffer */
- psd->psd_Ptr = psd->psd_Buffer;
- }
-
- if (!error && Bytes)
- {
- /*
- ** now there are only some bytes < SectorSize left, so they fit into one buffer
- ** So, read a buffer and copy some bytes from it to user-buffer.
- */
- RDBytes = Bytes;
- psd->psd_IO->io_Length = psd->psd_SectorSize;
- psd->psd_IO->io_Data = psd->psd_Buffer;
- psd->psd_IO->io_Offset = psd->psd_Pos + psd->psd_Offset;
-
- if (DoIO((struct IORequest *)psd->psd_IO))
- {
- *res2 = psd->psd_IO->io_Error;
- RDBytes = psd->psd_IO->io_Actual;
- }
-
- CopyMem(psd->psd_Buffer, Buffer, RDBytes);
-
- psd->psd_Pos += RDBytes;
- psd->psd_Ptr = psd->psd_Buffer + RDBytes;
- psd->psd_Left = psd->psd_SectorSize - RDBytes;
-
- Bytes -= RDBytes;
- }
-
- return LatchBytes - Bytes;
- }
- /*E*/
- /*F*/ STATIC LONG REGARGS RawWrite(GD gd, struct PrivateStreamData *psd,UBYTE *Buffer,LONG Bytes, LONG *res2)
- {
- LONG LatchBytes,WRBytes;
- BOOL error = FALSE;
-
- /* check bounds */
- if ((psd->psd_Pos + Bytes) > psd->psd_Len) Bytes = psd->psd_Len-psd->psd_Pos;
-
- LatchBytes = Bytes;
-
- d(("write %ld bytes\n",Bytes));
-
- /*
- ** first, take care for outstanding data
- */
- if (Bytes && psd->psd_Left)
- {
- WRBytes = (LONG)MIN((int)psd->psd_Left, (int)Bytes);
- CopyMem(Buffer, psd->psd_Ptr, WRBytes);
-
- psd->psd_Ptr += WRBytes; /* incr. position in buffer */
- psd->psd_Left -= WRBytes; /* decr. number of unused bytes */
-
- if (psd->psd_Left == 0) /* Buffer full ? */
- { /* then write it out */
- psd->psd_IO->io_Data = psd->psd_Buffer;
- psd->psd_IO->io_Length = psd->psd_SectorSize;
- psd->psd_IO->io_Offset = psd->psd_Pos + psd->psd_Offset;
- psd->psd_IO->io_Command = CMD_WRITE;
- if (DoIO((struct IORequest *)psd->psd_IO))
- {
- *res2 = psd->psd_IO->io_Error;
- WRBytes = psd->psd_IO->io_Actual;
- error = TRUE;
- d(("td-error %ld\n",psd->psd_IO->io_Error));
- }
-
- psd->psd_Ptr = psd->psd_Buffer; /* reset buffer pointers */
- psd->psd_Left = 0;
- }
-
- Buffer += WRBytes;
- Bytes -= WRBytes;
- psd->psd_Pos += WRBytes; /* incr. position in file */
- }
-
- if (!error && Bytes)
- {
- /*
- ** second, try to write as much blocks as possible directly from
- ** user buffer in one go, aVOIDing CopyMem() and multiple I/O-Requests
- */
- if (Bytes > psd->psd_SectorSize)
- {
- /* I don't like to use bit masking at this point */
- WRBytes = (Bytes / psd->psd_SectorSize) * psd->psd_SectorSize;
- d(("chunk %ld/%lx bytes\n",WRBytes,WRBytes));
- psd->psd_IO->io_Data = Buffer;
- psd->psd_IO->io_Length = WRBytes;
- psd->psd_IO->io_Offset = psd->psd_Pos + psd->psd_Offset;
- psd->psd_IO->io_Command = CMD_WRITE;
- if (DoIO((struct IORequest *)psd->psd_IO))
- {
- *res2 = psd->psd_IO->io_Error;
- WRBytes = psd->psd_IO->io_Actual;
- error = TRUE;
- d(("td-error %ld\n",psd->psd_IO->io_Error));
- }
-
- Buffer += WRBytes;
- Bytes -= WRBytes;
- psd->psd_Pos += WRBytes; /* incr. position in file */
-
- psd->psd_Ptr = psd->psd_Buffer; /* for safety, reset buffer pointers */
- psd->psd_Left = 0;
- }
- }
-
- if (!error && Bytes)
- {
- /*
- ** now there are only some bytes < SectorSize left, and they fit into one
- ** buffer.
- ** NOTE: the actual writing is delayed to Close() or further Write()'s
- */
- WRBytes = Bytes;
- CopyMem(Buffer, psd->psd_Buffer, WRBytes);
-
- psd->psd_Pos += WRBytes; /* incr. position in file */
- Bytes -= WRBytes;
-
- psd->psd_Ptr = psd->psd_Buffer + WRBytes; /* set position in buffer */
- psd->psd_Left = psd->psd_SectorSize - WRBytes; /* set number of unused bytes */
- }
-
- return LatchBytes - Bytes;
- }
- /*E*/
-
- /*F*/ STATIC GD creategd(VOID)
- {
- GD new;
- LOCALSYSBASE;
-
- if (new = AllocVec(sizeof(struct GlobalData), MEMF_ANY | MEMF_CLEAR))
- new->gd_SysBase = SysBase;
-
- return new;
- }
- /*E*/
- /*F*/ STATIC BOOL openres(GD gd)
- {
- BOOL rc = FALSE;
-
- d(("entered\n"));
-
- DOSBase = NULL;
- UtilityBase = NULL;
- gd->gd_Port = NULL;
-
- if (SysBase->lib_Version >= 37)
- {
- if (DOSBase = OpenLibrary("dos.library", 37))
- {
- if (UtilityBase = OpenLibrary("utility.library", 37))
- {
- if (gd->gd_Port = CreateMsgPort())
- {
- rc = TRUE;
- }
- else d(("no handler port\n"));
- }
- else d(("no utility V37\n"));
- }
- else d(("no dos V37\n"));
- }
- else d(("no exec V37\n"));
-
- d(("left: %ld\n",rc));
-
- return rc;
- }
- /*E*/
- /*F*/ STATIC VOID closeres(GD gd)
- {
- d(("freeing port\n"));
- if (gd->gd_Port) DeleteMsgPort(gd->gd_Port);
-
- d(("closing dos\n"));
- if (DOSBase) CloseLibrary(DOSBase);
-
- d(("closing utility\n"));
- if (UtilityBase) CloseLibrary(UtilityBase);
-
- FreeVec(gd);
- }
- /*E*/
-
-